package com.panopset.io;

import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import com.panopset.Logger;
import com.panopset.compat.Strings;

/**
 * Global replace directory processor.
 * 
 * @author Karl Dinwiddie.
 * 
 */
public final class GlobalReplace extends DirectoryProcessor {

	/**
	 * Drop blanks flag.
	 */
	private boolean dropBlanks;

	/**
	 * 
	 * @param value
	 *            Blank lines will be dropped during global replace if this is
	 *            set to true.
	 */
	public void setDropBlanks(final boolean value) {
		dropBlanks = value;
	}

	/**
	 * From String.
	 */
	private final String from;

	/**
	 * To String.
	 */
	private final String to;

	/**
	 * Extension to limit file types to.
	 */
	private final List<String> ext;

	/**
	 * @param dir
	 *            Directory to traverse.
	 * @param fromText
	 *            String to replace.
	 * @param toText
	 *            Replacement String.
	 * @param extension
	 *            File type to limit processing to, for example
	 *            &quot;.txt&quot;. All files will be processed if extension is
	 *            null or blank. Comma separated values accepted as well.
	 */
	public GlobalReplace(final File dir, final String fromText,
			final String toText, final String extension) {
		super(dir);
		from = fromText;
		to = toText;
		ext = new ArrayList<String>();
		StringTokenizer st = new StringTokenizer(extension, ",");
		while (st.hasMoreElements()) {
			String s = st.nextToken().trim();
			if (s.length() > 0 && s.indexOf(".") == 0) {
				s = s.substring(1);
			}
			if (s.length() > 0) {
				ext.add("." + s);
			}
		}
	}

	@Override
	protected void process(final File f) {
		if (ext.isEmpty()
				|| ext.contains(Strings.getExtension(f.getName()))) {
			Logger.log("Processing " + new Filez().getCanonicalPath(f));
			final StringWriter sw = new StringWriter();
			new FileProcessor.Builder()
					.fileAndListener(f, new FileProcessor.Listener() {

						@Override
						public void process(final FileProcessor processor,
								final String[] values) {
							for (String s : values) {
								if (dropBlanks && !Strings.isPopulated(s)) {
									continue;
								}
								sw.append(s.replace(from, to));
								sw.append(Strings.getEol());
							}
						}

						@Override
						public void finish(final FileProcessor processor) {
							// nothing to do here.
						}

					}).construct().exec();
			new ShortFile().saveStringToFile(sw.toString(), f);
		}
	}

}
